/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "AppService.h"
#include "named_stub.h"
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "mockcpp/mockcpp.hpp"
#include "gmock/gmock-actions.h"
#include "storage/huawei/HWCloudService.h"
#include "storage/huawei/HWInnerDef.h"
#include "kmcv3.h"
#include "PluginGeneralTypes.h"
#include "interface/CloudServiceInterface.h"

using namespace Module;
using namespace AppProtect;
using namespace std;
using namespace AppServiceExport;

class AppServiceTest : public testing::Test {
public:
    void SetUp();
    void TearDown();
    static void SetUpTestCase();
    static void TearDownTestCase();
};

// static LLTSTUB::Stub stubApp;

void AppServiceTest::SetUp()
{}

void AppServiceTest::TearDown()
{
    GlobalMockObject::verify();
}

void AppServiceTest::SetUpTestCase()
{}

void AppServiceTest::TearDownTestCase()
{}

char g_text[] = "test";
KMC_RET EncryptV3cSuccessSub(KMC_DOMAIN domain, const char *plainTxt, char **encText)
{
    return KMC_RET::KMC_SUCESS;
}

KMC_RET EncryptV3cSuccessNotNullSub(KMC_DOMAIN domain, const char *plainTxt, char **encText)
{
    *encText = g_text;
    return KMC_RET::KMC_SUCESS;
}

KMC_RET EncryptV3cErrSub(KMC_DOMAIN domain, const char *plainTxt, char **encText)
{
    return KMC_RET::KMC_FAIL;
}

void KmcFreeSub(char *mem)
{
    return;
}
char g_text1[] = "test1";
KMC_RET DecryptV3cSuccessSub(KMC_DOMAIN domain, char **plainTxt, const char *encTextB64)
{
    return KMC_RET::KMC_SUCESS;
}

KMC_RET DecryptV3cSuccessNotNullSub(KMC_DOMAIN domain, char **plainTxt, const char *encTextB64)
{
    *plainTxt = g_text1;
    return KMC_RET::KMC_SUCESS;
}

KMC_RET DecryptV3cErrSub(KMC_DOMAIN domain, char **plainTxt, const char *encTextB64)
{
    return KMC_RET::KMC_FAIL;
}

static bool StubJsonStringToStructFALSE(void *obj)
{
    return false;
}

static bool StubJsonStringToStructTRUE(void *obj)
{
    return true;
}

static OBSResult ListBucketsStub(Module::HWCloudService *cloudService,
    const std::unique_ptr<ListBucketsRequest>& request,
    std::unique_ptr<ListBucketsResponse>& resp)
{
    resp = std::make_unique<ListBucketsResponse>();
    resp->bucketList = {"bucket1", "bucket2"};
    OBSResult ret;
    return ret;
}

/*
 * 用例名称：Encrypt
 * 前置条件：无
 * check点：加密
 **/
TEST_F(AppServiceTest, Encrypt)
{
    LLTSTUB::Stub stubApp;
    std::string plainText;
    std::string cipherText;
    stubApp.set(KmcFree, KmcFreeSub);
    stubApp.set(EncryptV3c, EncryptV3cErrSub);
    int ret = Encrypt(plainText, cipherText);
    cipherText.clear();
    cipherText.clear();
    stubApp.reset(EncryptV3c);
    stubApp.set(EncryptV3c, EncryptV3cSuccessNotNullSub);
    ret = Encrypt(plainText, cipherText);
    EXPECT_EQ(ret, MP_SUCCESS);
    cipherText.clear();
    cipherText.clear();
    stubApp.reset(EncryptV3c);
    stubApp.set(EncryptV3c, EncryptV3cSuccessSub);
    ret = Encrypt(plainText, cipherText);
    stubApp.reset(EncryptV3c);
    stubApp.reset(KmcFree);
}

TEST_F(AppServiceTest, Encrypt1)
{
    std::string plainText;
    std::string cipherText;
    MOCKER_CPP(&EncryptV3c)
        .stubs()
        .will(returnValue(KMC_RET::KMC_FAIL));
    EXPECT_EQ(Encrypt(plainText, cipherText), MP_FAILED);
}

/*
 * 用例名称：Decrypt
 * 前置条件：无
 * check点：加密
 **/
TEST_F(AppServiceTest, Decrypt)
{
    LLTSTUB::Stub stubApp;
    std::string plainText;
    std::string cipherText;
    stubApp.set(KmcFree, KmcFreeSub);
    stubApp.set(DecryptV3c, DecryptV3cErrSub);
    int ret = Decrypt(plainText, cipherText);
    EXPECT_EQ(ret, Module::FAILED);
    stubApp.reset(DecryptV3c);
    stubApp.set(DecryptV3c, DecryptV3cSuccessNotNullSub);
    ret = Decrypt(plainText, cipherText);
    EXPECT_EQ(ret, Module::SUCCESS);
    stubApp.reset(DecryptV3c);
    stubApp.set(DecryptV3c, DecryptV3cSuccessSub);
    ret = Decrypt(plainText, cipherText);
    EXPECT_EQ(ret, Module::SUCCESS);
    stubApp.reset(DecryptV3c);
    stubApp.reset(KmcFree);
}

TEST_F(AppServiceTest, Decrypt1)
{
    LLTSTUB::Stub stubApp;
    std::string plainText;
    std::string cipherText;
    stubApp.set(KmcFree, KmcFreeSub);
    MOCKER_CPP(&DecryptV3c)
        .stubs()
        .will(returnValue(KMC_RET::KMC_SUCESS));
    int ret = Decrypt(plainText, cipherText);
    EXPECT_EQ(ret, Module::FAILED);
    stubApp.reset(KmcFree);
}

/*
 * 用例名称：TransformCloudServiceMsg
 * 前置条件：无
 * check点：加密
 **/
TEST_F(AppServiceTest, TransformCloudServiceMsg)
{
    StorageVerifyInfo cloudServiceMsg;
    AuthExtendInfo extendInfo;
    AppServiceExport::TransformCloudServiceMsg(cloudServiceMsg, extendInfo);
    extendInfo.useHttps = "1";
    AppServiceExport::TransformCloudServiceMsg(cloudServiceMsg, extendInfo);
    extendInfo.proxyEnable = "1";
    AppServiceExport::TransformCloudServiceMsg(cloudServiceMsg, extendInfo);
    extendInfo.certification = "test";
    AppServiceExport::TransformCloudServiceMsg(cloudServiceMsg, extendInfo);
}

/*
 * 用例名称：CheckApplication
 * 前置条件：无
 * check点：检查应用
 **/
TEST_F(AppServiceTest, CheckApplication)
{
    const OBSResult result;
    MOCKER_CPP(&Module::JsonHelper::JsonStringToStruct<AuthExtendInfo>)
        .stubs()
        .will(returnValue(false));
    ActionResult returnValue;
    ApplicationEnvironment appEnv;
    Application application;
    EXPECT_NO_THROW(AppServiceExport::CheckApplication(returnValue, appEnv, application));
}

/*
 * 用例名称：ListApplicationResourceV2
 * 前置条件：无
 * check点：列出应用资源
 **/
TEST_F(AppServiceTest, ListApplicationResourceV2)
{
    MOCKER_CPP(&Module::JsonHelper::JsonStringToStruct<AuthExtendInfo>)  // mockcpp 模板函数打桩
        .stubs()
        .will(returnValue(false));
    ResourceResultByPage returnValue;
    ListResourceRequest request;
    EXPECT_NO_THROW(AppServiceExport::ListApplicationResourceV2(returnValue, request));
    Application application;
    request.applications.push_back(application);
    EXPECT_NO_THROW(AppServiceExport::ListApplicationResourceV2(returnValue, request));
}

/*
 * 用例名称：ListApplicationResourceV2_SUCCESS
 * 前置条件：无
 * check点：列出应用资源
 **/
TEST_F(AppServiceTest, ListApplicationResourceV2_SUCCESS)
{
    StorageVerifyInfo verifyInfo;
    Module::HWCloudService cloudService(verifyInfo, obs_auth_switch::OBS_S3_TYPE);
    MOCKER_CPP_VIRTUAL(cloudService, &HWCloudService::ListBuckets)
                    .stubs()
                    .will(invoke(ListBucketsStub));
    ResourceResultByPage returnValue;
    ListResourceRequest request;
    AuthExtendInfo extendInfo{};
    int storageType = 2;
    extendInfo.storageType = storageType;
    extendInfo.useHttps = "0";
    ApplicationExtendInfo appExtendInfo{};
    appExtendInfo.storageType = "2";
    Module::JsonHelper::StructToJsonString(extendInfo, request.appEnv.auth.extendInfo);
    Module::JsonHelper::StructToJsonString(appExtendInfo, request.appEnv.extendInfo);
    AppServiceExport::ListApplicationResourceV2(returnValue, request);
    int result = 2;
    EXPECT_EQ(returnValue.total, result);
}

